import { Application } from "mydog";
import { cmd } from "../../config/cmd";
import { room_msg } from "../../config/proto/room";
import { DoudizhuAttributes } from "../../models/doudizhu";
import { UserAttributes } from "../../models/user";
import { PlayerManager } from "../game/playerManager";
import { DEF } from "./consts";

export class Room {
  private _app: Application;

  public id: number;             // id
  public name: string;           // 房间名称/游戏名称
  public gameMode: number;       // 游戏类型
  public owner: number;          // 房主uid
  public maxPlayers: number;     // 最大玩家数量
  public state: number;          // 房间状态

  public playerManager: PlayerManager;

  constructor(app: Application, id: number, name: string, gameMode: number) {
    this._app = app;

    this.id = id;
    this.name = !!name ? name : `${this.gameModeToString(gameMode)} ${id}`;
    this.gameMode = gameMode;

    this.owner = 0;
    this.maxPlayers = 0;
    this.state = 0;

    this.playerManager = new PlayerManager(this);
  }

  private gameModeToString(gameMode: number) {
    switch (gameMode) {
      case DEF.GAME.MODE.doudizhu: return '斗地主';
      case DEF.GAME.MODE.lushi: return '炉石';
      default: return '未知';
    }
  }

  public isFull() {
    return this.playerManager.getPlayerCount() >= this.maxPlayers;
  }

  public isPlayerInRoom(uid: number) {
    return this.playerManager.isPlayerInRoom(uid);
  }

  public initPlayers(users: Array<{ userInfo: UserAttributes, playerInfo: { sid: string, isRobot: boolean }, gameInfo: any }>) {
    for (let i = 0; i < users.length; i++) {
      const userInfo = users[i].userInfo;
      const playerInfo = users[i].playerInfo;
      const gameInfo = users[i].gameInfo as DoudizhuAttributes;
      const player = this.playerManager.addPlayer(userInfo.id, userInfo.nickname, playerInfo.sid, playerInfo.isRobot);
      player?.initGameInfo(gameInfo);
    }
  }

  public onMatch() {
    const players = this.playerManager.getAllPlayers();

    // 通知匹配的玩家
    let playerMsg: any;
    switch (this.gameMode) {
      case DEF.GAME.MODE.doudizhu:
        playerMsg = players.map(player => { return { uid: player.uid, nickname: player.nickname, state: player.state, isRobot: player.isRobot, doudizhu: player.gameInfo } });
        break;
      case DEF.GAME.MODE.lushi:
        break;
      default: break;
    }
    const msg: room_msg.s2c_onMatch = new room_msg.s2c_onMatch();
    msg.code = DEF.SYSTEM.MATCH_CODE.SUCCESS;
    msg.room = this;
    msg.players = playerMsg;
    this.sendMessageToAll(cmd.room_onMatch, msg);
  }

  public onPlayerAction(uid: number, action: number) {
    // 非坐下状态，不能准备
    const state = this.playerManager.getPlayerStateByUid(uid);

    if (action === DEF.PLAYER.ACTION.READY && state === DEF.PLAYER.STATE.SITDOWN) {
      this.playerManager.updatePlayerStateByUid(uid, DEF.PLAYER.STATE.READY);
      this.onPlayerStateChange(uid, DEF.PLAYER.STATE.READY, true);
    } else if (action === DEF.PLAYER.ACTION.SITDOWN && state === DEF.PLAYER.STATE.READY) {
      this.playerManager.updatePlayerStateByUid(uid, DEF.PLAYER.STATE.SITDOWN);
      this.onPlayerStateChange(uid, DEF.PLAYER.STATE.SITDOWN, true);
    } else if (action === DEF.PLAYER.ACTION.START && state === DEF.PLAYER.STATE.LOADING) {
      this.playerManager.updatePlayerStateByUid(uid, DEF.PLAYER.STATE.LOADED);
      // this.onPlayerStateChange(uid, DEF.PLAYER.STATE.LOADED, true);
    } else {
      console.log(`不支持玩家主动改变的状态 ${action}`);
      return;
    }

    // 全部准备
    if (this.playerManager.isAllPlayerReady()) {
      this.initGame();
    }
    // 游戏资源全部加载
    if (this.playerManager.isAllPlayerLoaded()) {
      this.startGame();
    }
  }

  //
  private initGame() {
    console.log(`----------------------- initGame ${this.id} -----------------------`)
    const uidsid = this.playerManager.getAllPlayersUidsid();
    const result = this._app.rpcAwait(DEF.SEVER.ID.DOUDIZHU).doudizhu.main.onInitGame(this.id, uidsid);
    if (result) {
      this.playerManager.updateAllPlayerState(DEF.PLAYER.STATE.LOADING);
    }
  }

  private startGame() {
    console.log(`----------------------- startGame ${this.id} -----------------------`)
    this.playerManager.updateAllPlayerState(DEF.PLAYER.STATE.PLAYING);
    this._app.rpc(DEF.SEVER.ID.DOUDIZHU).doudizhu.main.onStartGame(this.id);
  }

  private endGame() {
    console.log(`----------------------- endGame ${this.id} -----------------------`)
    this._app.rpcAwait(DEF.SEVER.ID.DOUDIZHU).doudizhu.main.onEndGame(this.id);
  }

  //
  public onPlayerStateChange(uid: number, state: number, toSelf: boolean) {
    const res: room_msg.s2c_onPlayerInfo = new room_msg.s2c_onPlayerInfo();
    res.type = DEF.PLAYER.UPDATE.UPDATE_STATE;
    res.player = { uid, state }

    if (toSelf) {
      this.sendMessageToAll(cmd.room_onPlayerInfo, res);
    } else {
      this.sendMessageToAllExceptUid(cmd.room_onPlayerInfo, uid, res);
    }
  }

  // message
  public sendMessageToUid(route: number, uid: number, msg: any) {
    const player = this.playerManager.getPlayerByUid(uid);
    if (!!player) {
      this._app.sendMsgByUidSid(route, msg, [{ uid: player.uid, sid: player.sid }]);
    }
  }

  public sendMessageToAll(route: number, msg: any) {
    const uidsid = this.playerManager.getAllPlayersUidsid();
    this._app.sendMsgByUidSid(route, msg, uidsid);
  }

  public sendMessageToAllExceptUid(route: number, uid: number, msg: any) {
    const uidsid = this.playerManager.getAllPlayersUidsidExceptUid(uid);
    this._app.sendMsgByUidSid(route, msg, uidsid);
  }
}
